package com.ctcf.ocr.engine.impl.service;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.ctcf.ocr.engine.api.entity.OcrResponse;
import com.ctcf.ocr.engine.api.service.IOcrService;
import com.ctcf.ocr.engine.impl.utils.HttpRequestUtils;
import com.ctcf.ocr.engine.impl.utils.ImageClearUtils;
import com.ctcf.ocr.engine.impl.utils.ImageTypeFilter;

import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.TessAPI;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import net.sourceforge.tess4j.util.LoadLibs;

@Service
public class OcrService implements IOcrService {

	private final static Logger logger = LoggerFactory.getLogger(OcrService.class);

	private String testResourcesPath = "";

	private ITesseract instance;

	private String LANGUAGE_PBC = "pbc";

	private static final String VAR_CHAR_WHITELIST = "tessedit_char_whitelist";

	private static final String WHITELIST_DEFAULT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";

	/**
	 * 如果初始化失败，返回true
	 * 
	 * @return
	 */
	private synchronized boolean initTesseract() {
		if (instance == null) {
			try {
				File tessDataFolder = LoadLibs.extractTessResources("tessdata");
				logger.info("语言包路径：{}", tessDataFolder.getPath());

				instance = new Tesseract(); // JNA Interface Mapping
				instance.setDatapath(tessDataFolder.getParent());// 指定语言包路径
				instance.setLanguage(LANGUAGE_PBC);// 指定自定义训练字库 不指定默认为英文字库 eng
				instance.setPageSegMode(7);// 告诉引擎,识别图片区域为单行文本
				instance.setOcrEngineMode(TessAPI.TessOcrEngineMode.OEM_TESSERACT_ONLY);//
				instance.setTessVariable(VAR_CHAR_WHITELIST, WHITELIST_DEFAULT);// 设置识别的字符集范围

				File testFilePath = new File(this.getClass().getResource("/testResources").getPath());
				testResourcesPath = testFilePath.getPath();// 测试文件资源路径

				logger.info("测试文件资源路径：{}", testResourcesPath);

			} catch (Exception e) {
				logger.error("初始化图片识别引擎异常", e);
			}
		}
		return (instance == null) ? true : false;
	}

	@Override
	public List<OcrResponse> recognizeBatch() {
		List<OcrResponse> lstResult = new ArrayList<OcrResponse>();
		boolean isNotReady = this.initTesseract();
		if (isNotReady) {
			return lstResult;
		}
		File fileDir = new File(testResourcesPath);
		if (!fileDir.isDirectory()) {
			return lstResult;
		}

		File[] fileList = fileDir.listFiles(new ImageTypeFilter(".jpg"));
		for (File imageFile : fileList) {
			try {
				OcrResponse response = new OcrResponse();
				response.setName(imageFile.getName());
				BufferedImage bufferedImage = null;
				BufferedImage img = null;
				try {
					img = ImageIO.read(imageFile);
					String base64Image = HttpRequestUtils.encodeToString(img, "PNG");
					response.setImage(base64Image);

					bufferedImage = ImageClearUtils.removeBackgroud(imageFile);
					String noExtName = imageFile.getPath().substring(0, imageFile.getPath().lastIndexOf("."));
					ImageIO.write(bufferedImage, "PNG", new File(noExtName + ".png"));

				} catch (Exception e) {
					logger.error("图片二值化处理异常！{}", e.getMessage(), e);
				}
				bufferedImage = (bufferedImage == null) ? img : bufferedImage;

				String text = instance.doOCR(bufferedImage);
				text = text.replaceAll("[\\r\\n\\t ]", "");// 替换字符串回车换行符、制表符和空格
				response.setText(text);
				logger.info("name={},text={}", response.getName(), response.getText());

				lstResult.add(response);
			} catch (TesseractException e) {
				logger.error("图形验证码识别异常,fileName={}", imageFile.getName(), e);
			}
		}
		return lstResult;
	}

	@Override
	public OcrResponse recognizeSingle(String fileName) {
		OcrResponse response = new OcrResponse();
		response.setName(fileName);

		boolean isNotReady = this.initTesseract();
		if (isNotReady) {
			return response;
		}

		File imageFile = new File(testResourcesPath + "/" + fileName + ".jpg");
		try {
			String text = instance.doOCR(imageFile);
			text = text.replaceAll("[\\r\\n\\t ]", "");// 替换字符串回车换行符、制表符和空格
			response.setText(text);
		} catch (TesseractException e) {
			logger.error("图形验证码识别异常,fileName={}", fileName, e);
		}
		return response;
	}

	@Override
	public List<OcrResponse> convertImageToTif() {
		List<OcrResponse> lstResult = new ArrayList<OcrResponse>();

		boolean isNotReady = this.initTesseract();
		if (isNotReady) {
			return lstResult;
		}

		File fileDir = new File(testResourcesPath);
		if (!fileDir.isDirectory()) {
			return lstResult;
		}

		File tifDir = new File(testResourcesPath + "/TIF");
		if (!tifDir.exists()) {
			tifDir.mkdirs();// 如果目录不存则创建
		}
		logger.info("TIF文件目录：{}", tifDir.getPath());
		File[] fileList = fileDir.listFiles(new ImageTypeFilter(".jpg"));
		for (File imageFile : fileList) {

			OcrResponse response = new OcrResponse();
			response.setName(imageFile.getName());
			BufferedImage bufferedImage = null;
			try {
				bufferedImage = ImageClearUtils.removeBackgroud(imageFile.getPath());
				String noExtName = imageFile.getName().substring(0, imageFile.getName().lastIndexOf("."));
				ImageIO.write(bufferedImage, "TIF", new File(tifDir.getPath() + "/" + noExtName + ".tif"));
				response.setText(noExtName + ".tif");
			} catch (Exception e) {
				logger.error("图片二值化处理异常！{}", e.getMessage(), e);
			}

			logger.info("JPG图片转换为TIF格式\t{}", response);
			lstResult.add(response);

		}
		return lstResult;
	}

	@Override
	public OcrResponse fetchImageFromPbc() {
		OcrResponse response = new OcrResponse();
		try {
			boolean isNotReady = this.initTesseract();
			if (isNotReady) {
				return response;
			}

			BufferedImage bufferedImage = null;
			BufferedImage image = HttpRequestUtils.fetchPbcVerifyCode();
//			File fileDir = new File(testResourcesPath);
//			File[] fileList = fileDir.listFiles(new ImageTypeFilter(".jpg"));
//			int count = fileList.length;
			//ImageIO.write(image, "JPG", new File(testResourcesPath + "/code" + count + ".jpg"));
			try {
				String base64Image = HttpRequestUtils.encodeToString(image, "PNG");
				response.setImage(base64Image);
				bufferedImage = ImageClearUtils.removeBackgroud(image);
			} catch (Exception e) {
				logger.error("图片二值化处理异常！{}", e.getMessage(), e);
			}
			bufferedImage = (bufferedImage == null) ? image : bufferedImage;

			String text = instance.doOCR(bufferedImage);

			text = text.replaceAll("[\\r\\n\\t ]", "");// 替换字符串回车换行符、制表符和空格
			response.setText(text);

			logger.info("text={}", response.getText());

		} catch (TesseractException e) {
			logger.error("图形验证码识别异常", e);
		}
		return response;
	}

}
